#include "assembler.h"
#include "tokens.h"

uint16_t token_for_register(enum reg r, bool is_a);
uint16_t token_for_x(enum x x);
uint16_t token_for_y(enum y y);
uint16_t token_for_op(enum op op);
uint16_t token_for_flag(enum flag f);

void disassemble_instruction(uint16_t *dst, int16_t *length, union instruction instruction) {
	uint16_t *src = dst;

	bool imm = instruction.b.w && instruction.b.a == instruction.b.b;
	if(imm) {
		*dst++ = token_for_register(instruction.b.a, true);
		*dst++ = 0x2603 /* snowman for now */;
	} else {
		if(instruction.b.w) {
			*dst++ = TOK_WRITE;
		}
		
		*dst++ = token_for_x(instruction.b.x);
		*dst++ = token_for_op(instruction.b.o);
		if(instruction.b.c) *dst++ = TOK_CARRY;
		*dst++ = token_for_y(instruction.b.y);
		
		if(instruction.b.f != FLAG_F) {
			*dst++ = token_for_flag(instruction.b.f);
		}
		
		*dst++ = token_for_register(instruction.b.a, true);
		*dst++ = token_for_register(instruction.b.b, false);
	}
	
	*dst = 0;
	*length = dst - src;
}

uint16_t token_for_register(enum reg r, bool is_a) {
	uint16_t symbols[2][8] = {
		{TOK_A_R0, TOK_A_R1, TOK_A_R2, TOK_A_R3, TOK_A_R4, TOK_A_R5, TOK_A_R6, TOK_A_R7},
		{TOK_B_R0, TOK_B_R1, TOK_B_R2, TOK_B_R3, TOK_B_R4, TOK_B_R5, TOK_B_R6, TOK_B_R7}
	};
		
	return symbols[is_a ? 0 : 1][r];
}

uint16_t token_for_x(enum x x) {
	uint16_t symbols[2] = {TOK_X_0, TOK_X_A};

	return symbols[x];
}

uint16_t token_for_y(enum y y) {
	uint16_t symbols[4] = {TOK_Y_A, TOK_Y_A_SHR, TOK_Y_B, TOK_Y_NOT_B};
	
	return symbols[y];
}

uint16_t token_for_op(enum op op) {
	uint16_t symbols[4] = {TOK_OP_SHL, TOK_OP_AND, TOK_OP_IOR, TOK_OP_ADD};
	
	return symbols[op];
}

uint16_t token_for_flag(enum flag f) {
	uint16_t symbols[8] = {'0', '1', '2', '3', '4', '5', '6', '7'};
	
	return symbols[f];
}
